package com.distribute.core.netty.handler;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.distribute.common.MsgObj;
import com.distribute.common.MsgType;
import com.distribute.common.NotifyPluginType;
import com.distribute.core.constants.CacheConstants;
import com.distribute.core.constants.LocalCacheConstants;
import com.distribute.core.core.BaseCacheManageCell;
import com.distribute.core.core.CacheManageContext;
import com.distribute.core.init.CacheReportClient;
import com.distribute.core.notify.DLCNotify;
import com.distribute.core.utils.SpringContextUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * 缓存客户端处理器
 *
 * @author chennengcheng
 * @date 2021-09-13 13:44
 * @remark
 */
@ChannelHandler.Sharable
public class CacheClientHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 本方法用于接收服务端发送过来的消息
     *
     * @param ctx
     * @param data
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String data) throws Exception {
        DLCNotify dlcNotify = SpringContextUtils.getBean(CacheConstants.REDIS_NOTIFY_COMPONENT_NAME, DLCNotify.class);
        MsgObj msgObj = JSONUtil.toBean(data, MsgObj.class);
        String dataJson = msgObj.getData();
        NotifyPluginType notifyPluginType = LocalCacheConstants.getNotifyPluginType();
        if (msgObj.getMsgType().equals(MsgType.FLUSH_CACHE_INFO_DATA)) {
            if (NotifyPluginType.REDIS.equals(notifyPluginType)){
                String[] nameValues = dataJson.split(StrUtil.COLON);
                String modelPrefixName = nameValues[0];
                String modelName = nameValues[1];
                dlcNotify.notifyCacheUpdateAll(modelPrefixName, modelName);
            }
        }

        if (msgObj.getMsgType().equals(MsgType.GET_CACHE_INFO_DATA)) {
            String[] nameValues = dataJson.split(StrUtil.COLON);
            String modelPrefixName = nameValues[0];
            String modelName = nameValues[1];
            String classNameFull = CacheManageContext.getClassNameByModeFullName(modelPrefixName, modelName);
            BaseCacheManageCell baseCacheManageCell = (BaseCacheManageCell) SpringContextUtils.getBean(classNameFull);
            // 如果通道正常
            Channel channel = ctx.channel();
            if (channel.isActive()) {
                String msg = baseCacheManageCell.getCacheDataJson();
                channel.writeAndFlush(JSONUtil.toJsonStr(
                        new MsgObj(MsgType.GET_CACHE_INFO_DATA,
                                msgObj.getKey(),
                                msg)
                ));
            }
        }

        if (msgObj.getMsgType().equals(MsgType.OPEN_CACHE_DATA)) {
            String[] nameValues = dataJson.split(StrUtil.COLON);
            String modelPrefixName = nameValues[0];
            String modelName = nameValues[1];
            String classNameFull = CacheManageContext.getClassNameByModeFullName(modelPrefixName, modelName);
            BaseCacheManageCell baseCacheManageCell = (BaseCacheManageCell) SpringContextUtils.getBean(classNameFull);
            baseCacheManageCell.openCache();
        }

        if (msgObj.getMsgType().equals(MsgType.CLOSE_CACHE_DATA)) {
            String[] nameValues = dataJson.split(StrUtil.COLON);
            String modelPrefixName = nameValues[0];
            String modelName = nameValues[1];
            String classNameFull = CacheManageContext.getClassNameByModeFullName(modelPrefixName, modelName);
            BaseCacheManageCell baseCacheManageCell = (BaseCacheManageCell) SpringContextUtils.getBean(classNameFull);
            baseCacheManageCell.closeCache();
        }
    }

    /**
     * 本方法用于处理异常
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        CacheReportClient.cacheClientHandler = null;
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 本方法用于向服务端发送信息
     * 此处还需要实现心跳
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        CacheReportClient.cacheClientHandler = ctx;
        // 修改状态为已连接
        LocalCacheConstants.setStatus("connected");
    }


}
